package com.pentalog.ginet;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.hibernate.Filter;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.pentalog.ginet.domain.Department;
import com.pentalog.ginet.domain.Employee;
import com.pentalog.ginet.domain.EmployeeDetail;
import com.pentalog.ginet.domain.Stock;
import com.pentalog.ginet.domain.StockDailyRecord;
import com.pentalog.ginet.util.HibernateUtil;

/**
 * Hello world!
 * 
 */
public class App {
	public static void main(String[] args) {
		App app = new App();
//		app.saveData();
//		app.filterData();
//		app.dynamicInsertData();
//		app.dynamicUpdateData();
//		app.updateMutable();
//		app.fetchingStrategies();
		app.fetchingStrategiesBatchSize();
//		app.demoGetOrLoadMethod();
//		app.saveDataEmployeeDepartment();
//		app.lazyLoadingData();
//		app.loadDataLazyAndEager();
	}
	/*
	 * demo lazy loading
	 */
	private void lazyLoadingData(){
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction tx = null;
		Employee lemployee = null;
		Department department = null;
		try {
			tx = session.beginTransaction();
			
			/*EmployeeDetail employeeDetail = new EmployeeDetail("10th Street", "LA", "San Francisco", "U.S.");
	        Employee employee = new Employee("Nina", "Mayers","114-857-965");

	        employee.setEmployeeDetail(employeeDetail);
	        employeeDetail.setEmployee(employee);*/
	        
	        
	        /*List<Employee> employees = new ArrayList<Employee>();
	        employees.add(employee);
	        Department department = new Department();
	        department.setDepartmentName("PR1");
	        department.setEmployees(employees);
	        session.save(department);*/
	        
	        
//	        session.save(employee);
	        
//	        lemployee = (Employee)session.createQuery("from Employee e where e.employeeId = 7").uniqueResult();
	        department = (Department)session.createQuery("from Department e where e.departmentId = 1").uniqueResult();
	        Employee e = (Employee)department.getEmployees().get(0);
//	        for (Employee employee2 : list) {
//				System.out.println(employee2.getFirstname());
//			}
//	        System.out.println(department.getEmployees().size());
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
//			System.out.println(lemployee.getEmployeeDetail().getState());
//			System.out.println(department.getEmployees().size());
		}
	}
	private void saveDataEmployeeDepartment(){
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			
	        Employee emp1 = new Employee("PRNina", "PRMayers", "111");
	        Employee emp2 = new Employee("PRTony", "PRAlmeida", "222");
	        
	        List<Employee> employees = new ArrayList<Employee>();
	        employees.add(emp1);
	        employees.add(emp2);

	        Department department = new Department();
	        department.setDepartmentName("PR");
	        department.setEmployees(employees);
	         
	        session.save(department);
			
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}
	/*
	 * Demo Fetching Strategies
	 * set @OneToMany(fetch = FetchType.LAZY, mappedBy = "stock") in Stock.java
	 * 1. Default set @Fetch(FetchMode.SELECT) --> 2 select statement (2 hit database)
	 * 2. set @Fetch(FetchMode.JOIN) --> 1 statement join
	 * or @BatchSize(size = 3)
	 * 
	 */
	private void fetchingStrategies() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction tx = null;
		Stock stock = null;
		try {
			tx = session.beginTransaction();
			stock = (Stock)session.get(Stock.class, 2); 
			Set sets = stock.getStockDailyRecords();
			 
			//call select from stock_daily_record
			for ( Iterator iter = sets.iterator();iter.hasNext(); ) { 
			      StockDailyRecord sdr = (StockDailyRecord) iter.next();
			      System.out.println(sdr.getRecordId());
			      System.out.println(sdr.getDate());
			}
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}
	/*
	 * Demo Fetching Strategies
	 * set @OneToMany(fetch = FetchType.LAZY, mappedBy = "stock") in Stock.java
	 * 1. set @Fetch(FetchMode.SELECT) and disable @BatchSize(size = 6)
	 * 2. add @BatchSize(size = 3)
	 * 
	 */
	private void fetchingStrategiesBatchSize() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction tx = null;
		try {
			List<Stock> list = session.createQuery("from Stock").list();
			for(Stock stock : list){			 
			    Set sets = stock.getStockDailyRecords();
			    for ( Iterator iter = sets.iterator();iter.hasNext(); ) { 
			            StockDailyRecord sdr = (StockDailyRecord) iter.next();
			            System.out.println(sdr.getRecordId());
			            System.out.println(sdr.getDate());
			    }
			}
		} catch (HibernateException e) {
		} finally {
			session.close();
		}
	}
	/*
	 *  Test update mutable: must add @Mutable in Stock.java
	 */
	private void updateMutable(){
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			
			Stock stock = (Stock)session.createQuery(
				      " from Stock where stockCode = '123VHZ'").uniqueResult();
			stock.setStockName("DIALOG1234");
			session.saveOrUpdate(stock);
			
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	private void loadDataLazyAndEager() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction tx = null;
		Stock stock = null;
		try {
			tx = session.beginTransaction();
			stock = (Stock)session.createQuery("FROM Stock s where s.stockId = 1").uniqueResult();
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			if(stock.getStockDailyRecords().size()>0){
				System.out.println("\n--- EAGER loading ---");
			}
			session.close();
		}
	}
//	Hibernate data filter example
	private void filterData() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction tx = null;
		Stock stock = null;
		try {
			tx = session.beginTransaction();
			Filter filter = session.enableFilter("stockRecordFilter");
	        filter.setParameter("stockRecordFilterParam", new Date());
	 
	        stock = (Stock)session.get(Stock.class, 4);
	        Set<StockDailyRecord> sets = stock.getStockDailyRecords();
	 
	        for(StockDailyRecord sdr : sets){
			System.out.println(sdr.getRecordId());
			System.out.println(sdr.getDate());
		}
	 
	        System.out.println("****** Disabled Filter ******");
	 
	        session.disableFilter("stockRecordFilter");
	        //clear the loaded instance and get Stock again, for demo only
	        session.evict(stock);
	 
	        Stock stock2 = (Stock)session.get(Stock.class, 4);
	        Set<StockDailyRecord> sets2 = stock2.getStockDailyRecords();
	 
	        for(StockDailyRecord sdr : sets2){
			System.out.println(sdr.getRecordId());
			System.out.println(sdr.getDate());
		}
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
			/*if(stock.getStockDailyRecords().size()>0){
				System.out.println("\n--- EAGER loading ---");
			}*/
		}
	}
	//Dynamic insert
	private void dynamicInsertData() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		session.beginTransaction();

		Stock stock = new Stock();
		String random = RandomStringUtils.randomAlphabetic(3).toUpperCase();
		stock.setStockCode("123" + random);
		stock.setStockName("Stock" + random);
		session.save(stock);
		
		session.getTransaction().commit();
		session.close();
	}
	//Dynamic update
	private void dynamicUpdateData() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		session.beginTransaction();

		Query q = session.createQuery("from Stock where stockId = :stockId ");
		q.setParameter("stockId", 2);
		Stock stockTran = (Stock) q.list().get(0);
		stockTran.setStockCode("ACB2");
		session.update(stockTran);
		
		session.getTransaction().commit();
		session.close();
	}

	/*
	 * This function demo different between get() and load() in hibernate
	 * 1. if using get() --> 2 statement appear : select and update
	 * 2. if using load() --> only statement: update
	 */
	private void demoGetOrLoadMethod() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction tx = null;
		Stock stock = null;
		try {
			tx = session.beginTransaction();
			stock = (Stock)session.get(Stock.class, new Integer(2));
			Float float_random = RandomUtils.nextFloat();
			StockDailyRecord stockDailyRecords = new StockDailyRecord();
			stockDailyRecords.setPriceOpen(float_random);
			stockDailyRecords.setPriceClose(float_random);
			stockDailyRecords.setPriceChange(float_random);
			stockDailyRecords.setVolume(29999L);
			stockDailyRecords.setDate(new Date());
			stockDailyRecords.setStock(stock);
			session.save(stockDailyRecords);
			
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}
	
	private void saveData() {
		System.out.println("Hibernate one to many (Annotation)");
		Session session = HibernateUtil.getSessionFactory().openSession();

		session.beginTransaction();

		Stock stock = new Stock();
		String random = RandomStringUtils.randomAlphabetic(3).toUpperCase();
		Float float_random = RandomUtils.nextFloat();
		stock.setStockCode("123" + random);
		stock.setStockName("PADINI" + random);

		session.save(stock);

		StockDailyRecord stockDailyRecords = new StockDailyRecord();
		stockDailyRecords.setPriceOpen(float_random);
		stockDailyRecords.setPriceClose(float_random);
		stockDailyRecords.setPriceChange(float_random);
		stockDailyRecords.setVolume(3000000L);
		stockDailyRecords.setDate(new Date());
		stockDailyRecords.setStock(stock);
		
		StockDailyRecord stockDailyRecords1 = new StockDailyRecord();
		stockDailyRecords1.setPriceOpen(RandomUtils.nextFloat());
		stockDailyRecords1.setPriceClose(RandomUtils.nextFloat());
		stockDailyRecords1.setPriceChange(RandomUtils.nextFloat());
		stockDailyRecords1.setVolume(3000000L);
		stockDailyRecords1.setDate(new Date(112,10,25));
		stockDailyRecords1.setStock(stock);

		session.save(stockDailyRecords);
		session.save(stockDailyRecords1);

		session.getTransaction().commit();
		session.close();
		System.out.println("Done");
	}
}
